package com.yj.mvc.web.servlet.view;

import cn.hutool.json.JSONUtil;
import com.yj.mvc.util.ReqPO;
import com.yj.mvc.web.controller.IndexController;
import com.yj.mvc.web.core.MappingValue;
import lombok.SneakyThrows;

import java.io.*;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

@Deprecated
public class DispatcherServletDeprecated {


    private Map<String, MappingValue> mappingValuesMap = new HashMap<>();
    private Map<String, Class<?>> mappingClazzMap = new HashMap<>();
    private Map<String, Object> mappingObjMap = new HashMap<>();


    public DispatcherServletDeprecated(){
        MappingValue value = new MappingValue("/doIndex", "com.yj.mvc.web.controller.IndexController", "doIndex");
        mappingClazzMap.put("com.yj.mvc.web.controller.IndexController", IndexController.class);
        mappingObjMap.put("com.yj.mvc.web.controller.IndexController", new IndexController());
        mappingValuesMap.put("/doIndex", value);
        accept();
    }

    @SneakyThrows
    private void accept() {

        ServerSocket serverSocket = new ServerSocket(8080);
        while (true) {
            Socket s = serverSocket.accept();
            InetAddress inetAddress = s.getInetAddress();
            System.out.println("Accept connection from " + inetAddress.getHostAddress());


            new Thread(() -> {
                try (Socket socket = s;
                     BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {

                    String request = reader.readLine();
                    if (request != null && request.startsWith("GET ") && request.contains("HTTP/1.1")) {
                        if (request.contains("favicon.ico")) {
                            System.out.println("Ignoring favicon request");
                            return;
                        }
                        doseRequest(request, reader, writer);  // 处理请求的方法
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }).start();

        }

    }

    private void doseRequest(String request, BufferedReader reader, BufferedWriter writer) throws IOException {


        String[] uriLine =request.split(" ");
        String url = uriLine[1].split("\\?")[0];
        String params = uriLine[1].split("\\?")[1];

        ReqPO reqPO = new ReqPO();
        reqPO.setUrl(url);
        reqPO.setParams(params);

        doDispatch(reqPO, reader, writer);
    }

    private void doDispatch(ReqPO reqPO, BufferedReader reader, BufferedWriter writer) {
        try {
            String reqUrl = reqPO.getUrl();
            MappingValue mappingValue = mappingValuesMap.get(reqUrl);
            if (mappingValue == null) {
                System.out.println("No mapping value found for " + reqUrl);

                writer.write("No mapping value found for " + reqUrl);
                return;
            }
            String id = mappingValue.getId();
            String className = mappingValue.getClassName();
            Class<?> clazz = mappingClazzMap.get(className);
            if (clazz == null) {
                System.out.println("No class found for " + id);
                writer.write("No class found for " + id);
                return;
            }
            Object obj = mappingObjMap.get(className);
            String methodName = mappingValue.getMethodName();

            String params = reqPO.getParams();
            Object[] parameters = null;
            Class[] parameterTypes = null;
            if (params.contains("\\&")){
                String[] paramsArr = params.split("&");
                parameters = new Object[paramsArr.length];
                parameterTypes = new Class[paramsArr.length];
                for (int i = 0; i < paramsArr.length; i++) {
                     String paramName = paramsArr[i].split("=")[0];
                     Object paramValue = paramsArr[i].split("=")[1];
                     if (paramValue instanceof Integer){
                         parameters[i] = paramValue;
                         parameterTypes[i] = Integer.class;
                     }else if (paramValue instanceof Double){
                         parameters[i] = paramValue;
                         parameterTypes[i] = Double.class;
                    }else if (paramValue instanceof Boolean){
                         parameters[i] = paramValue;
                         parameterTypes[i] = Boolean.class;
                     }else {
                         parameters[i] = paramValue;
                         parameterTypes[i] = String.class;
                     }
                }
            }




            Method targetMethod = clazz.getDeclaredMethod(methodName, parameterTypes);


            Object result = targetMethod.invoke(obj, parameters);


            doResponse(result,writer);




        }catch (Exception e){
            e.printStackTrace();
        }

    }

    @SneakyThrows
    private void doResponse(Object result, BufferedWriter writer) {

        String respStr = JSONUtil.toJsonStr(result);


        writer.write("HTTP/1.1 200 OK\r\n");
        writer.write("Content-Type application/json\r\n");
        writer.write("\r\n");
        writer.write(respStr);
        writer.flush();

    }


}
